package com.yunji.order.business.delay;

import com.yunji.order.domain.OrderDO;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RBlockingQueue;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @Project: yunji-coffee
 * @Package: com.yunji.framework.config
 * @Title: RedissonQueue
 * @Description: redis队列
 * <p>
 * History:
 * Date						Version			Author			Summary
 * ========================================================================
 * 2024-04-20 14:58:27		V1.0			HuaAo		新建类
 */
@Component
public class RedissonQueue {
    private static final Logger logs = LoggerFactory.getLogger(RedissonQueue.class);

    public static boolean stop = false;

    // 订单队列
    public static final String CLOSE_QUEUE = "closeQueue";

    // 解冻队列
    public static final String SCALE_QUEUE = "scaleQueue";


    public static final String DELIVERED_QUEUE = "deliveredQueue";

    @Value("${expire.ttl.order:300}")
    private Long orderTime;
    @Value("${expire.ttl.scale:1}")
    private Long scaleTime;
    @Value("${expire.ttl.delivered:5}")
    private Long deliveredTime;

    @Resource
    private RedissonClient client;

    @Resource
    private ThreadPoolTaskExecutor scheduledThreadPoolExecutor; //线程

    @Resource
    private CloseOrderHandler closeOrderHandler;

    @Resource
    private OrderScaleHandler orderScaleHandler;

    @Resource
    private DeliveredHandler deliveredHandler;

    private static Boolean flag = Boolean.FALSE;

    /**
     * @Title closeOrder
     * @Desc 延时关闭订单
     * @Date 2024-04-20 16:17:38.134
     */
    public synchronized void start() {
        if (Boolean.TRUE.equals(flag)) {
            return;
        }
        RBlockingDeque<OrderDO> closeDeque = client.getBlockingDeque(CLOSE_QUEUE);
        scheduledThreadPoolExecutor.execute(new OrderTimer(closeDeque, closeOrderHandler));
        RBlockingDeque<OrderDO> scaleDeque = client.getBlockingDeque(SCALE_QUEUE);
        scheduledThreadPoolExecutor.execute(new OrderTimer(scaleDeque, orderScaleHandler));
        RBlockingDeque<OrderDO> deliveredDeque = client.getBlockingDeque(DELIVERED_QUEUE);
        scheduledThreadPoolExecutor.execute(new OrderTimer(deliveredDeque, deliveredHandler));
        flag = Boolean.TRUE;
    }

    private class OrderTimer implements Runnable {
        RBlockingDeque<OrderDO> blockingDeque;
        BusinessHandler instance;

        public OrderTimer(RBlockingDeque<OrderDO> blockingDeque, BusinessHandler instance) {
            this.blockingDeque = blockingDeque;
            this.instance = instance;
        }

        @Override
        public void run() {
            while (!stop) {
                try {
                    // blockqueue,当拿到数据时,才往下执行.没有则等待
                    OrderDO order = blockingDeque.take();
                    scheduledThreadPoolExecutor.execute(new OrderTask(order, instance));
                } catch (Exception e) {
                    logs.error("Redisson 已停机:{}", e.getMessage(), e);
                    Thread.currentThread().interrupt();
                    System.exit(1);
                }
            }
        }
    }

    private static class OrderTask implements Runnable {
        OrderDO order;

        BusinessHandler instance;

        public OrderTask(OrderDO order, BusinessHandler instance) {
            this.order = order;
            this.instance = instance;
        }

        @Override
        @Transactional
        public void run() {
            instance.process(order);
        }
    }

    /**
     * @param order 订单信息
     * @Title setOrderQueue
     * @Desc 设置订单延时关闭队列
     * @Date 2024-04-25 15:28:36.743
     */
    public void setCancelQueue(OrderDO order) {
        //阻塞队列
        RBlockingQueue<OrderDO> blockingQueue = client.getBlockingQueue(CLOSE_QUEUE);
        //延迟队列
        RDelayedQueue<OrderDO> delayedQueue = client.getDelayedQueue(blockingQueue);

        delayedQueue.offer(order, orderTime, TimeUnit.SECONDS);
    }

    /**
     * @param order 订单信息
     * @Title setScaleQueue
     * @Desc 设置订单延时解冻队列
     * @Date 2024-04-25 15:27:59.989
     */
    public void setScaleQueue(OrderDO order) {
        //阻塞队列
        RBlockingQueue<OrderDO> blockingQueue = client.getBlockingQueue(SCALE_QUEUE);
        //延迟队列
        RDelayedQueue<OrderDO> delayedQueue = client.getDelayedQueue(blockingQueue);

        delayedQueue.offer(order, scaleTime, TimeUnit.MINUTES);
    }

    /**
     * @param order 订单信息
     * @Title setDeliveredQueue
     * @Desc 设置订单延时发货队列
     * @Date 2024-04-25 15:27:22.434
     */
    public void setDeliveredQueue(OrderDO order) {
        //阻塞队列
        RBlockingQueue<OrderDO> blockingQueue = client.getBlockingQueue(DELIVERED_QUEUE);
        //延迟队列
        RDelayedQueue<OrderDO> delayedQueue = client.getDelayedQueue(blockingQueue);

        delayedQueue.offer(order, deliveredTime, TimeUnit.SECONDS);
    }
}